#include "uart_com.h"

#if (LV_USE_FS_POSIX == 1)
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>

#include "linux_link.h"


void tx_fifo_ForUart(void);
void Comm_have_buff_tx(uint8_t *SendBuff, uint8_t fun, uint8_t *data, uint16_t datalen);

void linux_rx(uint8_t fun, uint8_t *data, uint16_t len);

struct 
{
	uint8_t data[512];
	uint8_t len;
} tx_fifo = {
	.len = 0,
};


AcRxTemp_t AcRx = {
	.fd = 0,
	.analysis_fun = linux_rx,
	.step = 0,
	.cnt  = 0,
};

/********* 发送部分 ***********/
/**
 * @brief  通信发送底层函数
 * @param  void
 * @retval void
 */
void Comm_have_buff_tx(uint8_t *SendBuff, uint8_t fun, uint8_t *data, uint16_t datalen)
{
    uint16_t len = 0;

    /* 帧头 */
    SendBuff[len++] = 0xFD;
    SendBuff[len++] = 0xDF;

    /* 总长度 先占位 */
    SendBuff[len++] = 0;
		SendBuff[len++] = 0;
	
    /* 功能帧 */
    SendBuff[len++] = fun;

    /* 数据 */
    for (int max = (datalen + len), now = len; len < max; len++) {
        SendBuff[len] = data[len - now];
    }

    /* 获取实际长度 */
    SendBuff[2] = len >> 8;
		SendBuff[3] = len & 0xff;

    /* 校验位 */
    SendBuff[len] = 0;
    for (int i = 0; i < len; i++) {
        SendBuff[len] += SendBuff[i];
    }
}

/**
 * @brief  通信发送底层函数
 * @param  void
 * @retval void
 */
void Comm_tx(uint8_t fun, uint8_t *data, uint8_t datalen)
{
    uint8_t SendBuff[254];
    uint8_t len = 0;

    /* 帧头 */
    SendBuff[len++] = 0xFD;
    SendBuff[len++] = 0xDF;

    /* 总长度 先占位 */
    SendBuff[len++] = 0;
		SendBuff[len++] = 0;
	
    /* 功能帧 */
    SendBuff[len++] = fun;

    /* 数据 */
    for (int max = (datalen + len), now = len; len < max; len++) {
        SendBuff[len] = data[len - now];
    }

    /* 获取实际长度 */
    SendBuff[2] = len >> 8;
	SendBuff[3] = len & 0xff;

    /* 校验位 */
    SendBuff[len] = 0;
    for (int i = 0; i < len; i++) {
        SendBuff[len] += SendBuff[i];
    }

	if (tx_fifo.len == 0) {
		memcpy(&tx_fifo.data[0], SendBuff, len+1);
		tx_fifo.len = len+1;

		// printf("succeed 复制\n");
	}
	
	tx_fifo_ForUart();
	// write(AcRx.fd, SendBuff, len);
}

char send_buffer[BUFFER_SIZE];

void tx_fifo_ForUart(void)
{
	if (tx_fifo.len == 0) {
		return;
	}

	// printf("start tx\n");
	size_t bytes_written = write(AcRx.fd, &tx_fifo.data[0], tx_fifo.len);
	tx_fifo.len = 0;

	if (bytes_written == -1) {
		// perror("write");
	} else {
		// printf("succeed tx %d\n", bytes_written);
	}
}

/**
 * @brief  发送8位数据
 * @param  void
 * @retval void
 */
void Comm_tx_uint8(uint8_t fun, uint8_t data)
{
    uint8_t txdata = (uint8_t)data;

    Comm_tx(fun, &txdata, 1);
}

/**
 * @brief  发送16位数据
 * @param  void
 * @retval void
 */
void Comm_tx_uint16(uint8_t fun, uint16_t data)
{
    uint8_t txdata[2];
    txdata[0] = (uint8_t)(data >> 8);
    txdata[1] = (uint8_t)data;

    Comm_tx(fun, txdata, 2);
}

/********* 接收部分 **********/
/**
 * @brief  校验位计算
 * @param  void
 * @retval void
 */
static uint8_t rx_verify(uint8_t *data, uint16_t len)
{
	uint8_t verify = 0x00U;
	
	for (uint16_t i=0; i < len; i++) {
		verify += data[i];
	}	
	
	return verify;
}

/**
 * @brief  串口位置解析
 * @param  void
 * @retval void
 */
static void Position_Analysis(AcRxTemp_t * AcRxTemp, uint8_t data[])
{
	uint16_t len = (data[2] << 8) | data[3];
	
	if ( rx_verify(data, len) == data[len]) {	/* 校验通过 */
		AcRxTemp->analysis_fun(data[4], &data[5], len);
	}
}

/**
 * @brief  通过串口接收命令
 * @param  void
 * @retval void
 */
void ActionRx_ForUart(AcRxTemp_t * AcRxTemp, uint8_t data)
{
	switch(AcRxTemp->step) {
		case 0:
			AcRxTemp->cnt = 0;
			AcRxTemp->buff[AcRxTemp->cnt++] = data;
			if (data == 0xFD) {
				AcRxTemp->step = 1;
			}
			break;
		case 1:
			AcRxTemp->buff[AcRxTemp->cnt++] = data;
			if (data == 0xDF) {
				AcRxTemp->step = 2;
			} else {
				AcRxTemp->step = 0;
			}
			break;
		case 2:
			AcRxTemp->buff[AcRxTemp->cnt++] = data;
		
			if (AcRxTemp->cnt - 1 == 2) {
				return ;
			}
		
			if (AcRxTemp->cnt - 1 == 3) {
				AcRxTemp->rxlen = (AcRxTemp->buff[2] << 8) | AcRxTemp->buff[3];
			}
			
			if (AcRxTemp->cnt > AcRxTemp->rxlen) {
				AcRxTemp->step = 3;
				AcRxTemp->cnt = 0;
			}
			
			break;
			
		default :
		{};
	}
	
	if (AcRxTemp->step == 3) {
		AcRxTemp->step = 0;
		Position_Analysis(AcRxTemp, AcRxTemp->buff);
	}
}

pthread_t recv_thread, send_tid;

// 接收线程函数
static void *receive_thread(void *arg)
{
    char buffer;

	Comm_tx_uint8(LINUX_LINK_BUZZ, 1);

    while (1) {
		/* 接收数据 */
        ssize_t bytes_read = read(AcRx.fd, &buffer, 1);
        if (bytes_read > 0) {
			for (int i = 0; i < bytes_read; i++) {
				ActionRx_ForUart(&AcRx, buffer);
			}
        }

		//usleep(1000);
    }
    return NULL;
}

static int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;
	/* 获取fd串口对应的termios结构体，这步主要是查询串口是否启动正常 */
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 
		perror("SetupSerial 1");
		return -1;
	}
	//清空
	bzero( &newtio, sizeof( newtio ) );
	newtio.c_cflag  |=  CLOCAL | CREAD;	//配置成本地模式(本地连接、不改变端口所有者)、可读
	newtio.c_cflag &= ~CSIZE;		//清空数据位设置
	/* 选择数据位 */
	switch( nBits )
	{
	case 7:
		newtio.c_cflag |= CS7;
		break;
	case 8:
		newtio.c_cflag |= CS8;	
		break;
	}
	/* 选择校验位 */
	switch( nEvent )
	{
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);	//启用输入奇偶检测、去掉第八位
		break;
	case 'E': 
		newtio.c_iflag |= (INPCK | ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':  
		newtio.c_cflag &= ~PARENB;
		break;
	}
	/* 选择波特率 */
	switch( nSpeed )
	{
	case 2400:
		cfsetispeed(&newtio, B2400);
		cfsetospeed(&newtio, B2400);
		break;
	case 4800:
		cfsetispeed(&newtio, B4800);
		cfsetospeed(&newtio, B4800);
		break;
	case 9600:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	case 115200:
		cfsetispeed(&newtio, B115200);
		cfsetospeed(&newtio, B115200);
		break;
	case 460800:
		cfsetispeed(&newtio, B460800);
		cfsetospeed(&newtio, B460800);
		break;
	default:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	}
	/* 选择停止位，貌似linux下不能设置(1.5 0.5)停止位 */
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		newtio.c_cflag |=  CSTOPB;
	newtio.c_cc[VTIME]  = 0;
	newtio.c_cc[VMIN] = 0;
	tcflush(fd,TCIFLUSH);
	/* 设置新配置 */
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
//	printf("set done!\n\r");
	return 0;
}

struct termios options;

/**
 * @brief  定位系统初始化
 * @param  void
 * @retval void
 */
void Action_init(void)
{
	printf("start uart init\n");
	
	// 打开串口
	AcRx.fd = open(SERIAL_PORT, O_RDWR|O_NOCTTY|O_NDELAY );
	if (AcRx.fd == -1) {
		perror("open_port: Unable to open port");
		return ;
	}

	set_opt(AcRx.fd, 115200, 8, 'N', 1); //设置串口

	// // 获取当前串口设置
	// if (tcgetattr(AcRx.fd, &options) != 0) {
	// 	perror("tcgetattr");
	// 	close(AcRx.fd);
	// 	return ;
	// }

	// // 设置波特率为 115200
	// cfsetispeed(&options, B115200);
	// // cfsetospeed(&options, B115200);

	// // cfsetispeed(&options, B115200);
	// // cfsetospeed(&options, B115200);

	// // 设置数据位为 8 位
	// options.c_cflag &= ~CSIZE;
	// options.c_cflag |= CS8;

	// // 设置无校验位
	// options.c_cflag &= ~PARENB;

	// // 设置停止位为 1 位
	// options.c_cflag &= ~CSTOPB;

	// // 设置为原始模式
	// options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
	// options.c_oflag &= ~OPOST;

	// // 应用设置
	// if (tcsetattr(AcRx.fd, TCSANOW, &options) != 0) {
	// 	perror("tcsetattr");
	// 	close(AcRx.fd);
	// 	return ;
	// }

	// // 创建接收线程
    // if (pthread_create(&recv_thread, NULL, receive_thread, &AcRx.fd) != 0) {
    //     perror("pthread_create");
    //     close(AcRx.fd);
    //     return ;
    // }
}

#endif
/******************* (C) COPYRIGHT 2025 FUYEBING*****END OF FILE************/
